
package ohos.histreamer.demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.libsdl.SDL2;

import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

@SuppressWarnings("ALL")
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "HST_Demo";

    private String directory;

    private boolean isPlay;
    private boolean isSingleCycle;

    private ImageButton btnRepeat;
    private ImageButton btnPlay;
    private ImageButton btnPlayList;
    private SeekBar seekBar;
    private TextView timeStartView;
    private TextView timeEndView;
    private TextView songNameView;
    private Handler mHandler = new Handler();
    private PlayList playList;
    private Runnable mRun = new Runnable() {
        @Override
        public void run() {
            if (isPlay) {
                long duration = getDuration();
                long curTime = getCurrentTime();
                int span = seekBar.getMax() - seekBar.getMin();
                int curPos = 0;
                if (duration > 0) {
                    curPos = (int) (span * curTime * 1.0 / duration);
                }
                String showTxt = buildDisplayTime(curTime);
                runOnUiThread(() -> {
                    timeStartView.setText(showTxt);
                });
                seekBar.setProgress(curPos);
                Log.d(TAG, "update progress: " + curPos + ", duration: " + duration + ", curTime: " + curTime);
            }
            mHandler.postDelayed(mRun, 500);
        }
    };

    static {
        System.loadLibrary("jni_helper");
        System.loadLibrary("app_jni");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RequestPermission.requestPermission(this);
        directory = getExternalFilesDir(Environment.DIRECTORY_MUSIC).getAbsolutePath();
        Log.i(TAG, "Music directory is " + directory);
        copyRaw();
        playList = new PlayList(directory, this);
        SDL2.nativeInit();
        nativeInit();
        bindViews();
        String uri = playList.getSelectedFilename();
        setDataSource(uri);
        updateSongName(uri);
        mHandler.postDelayed(mRun, 10);
    }

    private void updateSongName(String uri)
    {
        runOnUiThread(() -> {
            songNameView.setText(Paths.get(uri).getFileName().toString());
        });
    }

    private void bindRepeatView() {
        btnRepeat = findViewById(R.id.btnListCycle);
        isSingleCycle = false;
        btnRepeat.setImageDrawable(getDrawable(R.drawable.ic_list_cycle));
        btnRepeat.setOnClickListener(v -> {
            if (!isSingleCycle) {
                isSingleCycle = true;
                btnRepeat.setImageDrawable(getDrawable(R.drawable.ic_single_cycle));
            } else {
                isSingleCycle = false;
                btnRepeat.setImageDrawable(getDrawable(R.drawable.ic_list_cycle));
            }
            setLooping(isSingleCycle);
        });
    }

    private String buildDisplayTime(long timestampUs) {
        long msec = timestampUs / 1000;
        String showTxt = String.valueOf(msec % 60);
        showTxt = ":" + showTxt;
        showTxt = String.valueOf(msec/60) + showTxt;
        return showTxt;
    }

    private void bindPlayView() {
        songNameView = findViewById(R.id.song_name);
        timeStartView = findViewById(R.id.time_start);
        timeEndView = findViewById(R.id.time_end);
        btnPlay = findViewById(R.id.audio_play);
        isPlay = false;
        btnPlay.setImageDrawable(getDrawable(R.drawable.ic_play));
        btnPlay.setOnClickListener(v -> {
            if (!isPlay) {
                isPlay = true;
                new Thread(() -> {
                    play();
                }).start();
                btnPlay.setImageDrawable(getDrawable(R.drawable.ic_pause));
            } else {
                isPlay = false;
                pause();
                btnPlay.setImageDrawable(getDrawable(R.drawable.ic_play));
            }
        });
    }

    private void bindSeekBarView() {
        seekBar = findViewById(R.id.audio_process);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

            @Override
            public void onProgressChanged(SeekBar seekBar, int progressValue, boolean fromUse) {
                Log.d(TAG, "seekbar on ProgressChanged: " + progressValue + ", fromUse: " + fromUse);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                Log.d(TAG, "seekbar, start track: " + seekBar.getProgress());
                mHandler.removeCallbacks(mRun);
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                int progress = seekBar.getProgress();
                long duration = getDuration();
                int span = seekBar.getMax() - seekBar.getMin();
                long msec = duration * progress / span;
                Log.d(TAG, "seekbar, stop track: " + progress + ", duration: " + duration + ",seekTime: " + msec);
                String showTxt = buildDisplayTime(msec);
                runOnUiThread(() -> {
                    timeStartView.setText(showTxt);
                });
                seekTo(msec);
                Log.d(TAG, "seekbar, curTime: " + getCurrentTime());
                mHandler.postDelayed(mRun, 10);
            }
        });
    }

    private void bindPlayListView() {
        btnPlayList = findViewById(R.id.play_list);
        btnPlayList.setImageDrawable(getDrawable(R.drawable.ic_playlist));
        btnPlayList.setOnClickListener(v -> {
            playList.show();
        });
    }
    private void bindViews() {
        bindPlayView();
        bindSeekBarView();
        bindRepeatView();
        bindPlayListView();
    }

    private void copyRaw() {
        String audio = directory + File.separator + "test.mp3";
        File audioFile = new File(audio);
        if (!audioFile.exists()) {
            try (//InputStream inputStream = getResources().getAssets().open("file:///android_asset/dream_it_possible.mp3"); 
                InputStream inputStream = getResources().openRawResource(R.raw.dream_it_possible);
                FileOutputStream fos = new FileOutputStream(audioFile)) {
                byte[] buffer = new byte[inputStream.available()];
                int lenght = 0;
                while ((lenght = inputStream.read(buffer)) != -1) {
                    fos.write(buffer, 0, lenght);
                }
                fos.flush();
            } catch (Exception e) {
            }
        }
    }

    private void stop() {
        isPlay = false;
        mHandler.removeCallbacks(mRun);
        seekBar.setProgress(0);
        nativeStop();
    }

    public void play(String uri) {
        Log.d(TAG, "play uri: " + uri);
        stop();
        setDataSource(uri);
        updateSongName(uri);
        btnPlay.callOnClick();
        mHandler.postDelayed(mRun, 10);
    }

    public void onCompelete() {
        if (!isSingleCycle) {
            isPlay = false;
            runOnUiThread(() -> btnPlay.setImageDrawable(getDrawable(R.drawable.ic_play)));
        }
        seekBar.setProgress(0);
        String showTxt = buildDisplayTime(0);
        runOnUiThread(() -> {
            timeStartView.setText(showTxt);
            String uri = playList.getSelectedFilename();
            setDataSource(uri);
            updateSongName(uri);
        });
        Log.d(TAG, "onCompelete: finished");
    }

    public void onError(String str) {
        runOnUiThread(()->{
            Toast.makeText(MainActivity.this, str, Toast.LENGTH_LONG).show();
            btnPlay.setImageDrawable(getDrawable(R.drawable.ic_play));
            stop();
        });
    }

    public void onStateChanged(String state) {
        Log.d(TAG, "onStateChanged: " + state);
        if (state.equals("PlayingState")) {
            long duration = getDuration();
            Log.d(TAG, "onReady: "+ duration / 1000);
            String showTxt = buildDisplayTime(duration);
            runOnUiThread(() -> {
                timeEndView.setText(showTxt);
            });
        }
    }

    public native void nativeInit();

    public native void setDataSource(String uri);

    public native void setLooping(boolean looping);

    public native void play();

    public native void nativeStop();

    public native void pause();

    public native void seekTo(long time);

    public native long getDuration();

    public native long getCurrentTime();
}
